package com.lipaluma.csv.io;
import static org.joox.JOOX.$;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Element;

import com.lipaluma.csv.annotations.config.CSV;
import com.lipaluma.io.SourceFactory;
import com.lipaluma.io.SourceReader;
import com.lipaluma.io.SourceWriter;
/**
 * ConfigurationFile for CSV entry File
 * @author Mario
 */
public class CsvSourceFactory implements SourceFactory {
	public static final String CSV_TYPE = "CSV";
	
	public static final char CSV_DEFAULT_DELIMITER = ',';
	public static final char CSV_DEFAULT_QUOTE = '"';
	
	private Character delimiter;
	private Character quote; 
	private boolean trimValues; 
	
	/**
	 * Constructs a default file Configuration for CSV.
	 * <p>
	 * The delimiter is ','<br>
	 * the quote is '"'<br>
	 * by default, the process trim all values.
	 */
	public CsvSourceFactory() {
		this.delimiter = CSV_DEFAULT_DELIMITER;
		this.quote = CSV_DEFAULT_QUOTE;
		this.trimValues = true;
	}

	/**
	 * Constructs a file Configuration for CSV with specified delimiter.
	 * <p>
	 * the quote is '"'<br>
	 * by default, the process trim all values.
	 * @param delimiter the delimiter
	 */
	public CsvSourceFactory(char delimiter) {
		this.delimiter = delimiter;
		this.quote = CSV_DEFAULT_QUOTE;
		this.trimValues = true;
	}

	/**
	 * Constructs a file Configuration for CSV with all parameters defined.
	 * 
	 * @param delimiter the delimiter
	 * @param quote the quote
	 * @param trimAll trim all values ?
	 */
	public CsvSourceFactory(char delimiter, char quote, boolean trimAll) {
		this.delimiter = delimiter;
		this.quote = quote;
		this.trimValues = trimAll;
	}
	
	/**
	 * Constructs a file Configuration for CSV with the annotation {@link CSV}
	 * @param csv the csv annotation
	 */
	public CsvSourceFactory(CSV csv) {
		this.delimiter = csv.delimiter();
		this.quote = csv.quote();
		this.trimValues = csv.trimAll();
	}

	/**
	 * Constructs a file Configuration for CSV by xml configuration file
	 * @param Element root of the file
	 */
	public CsvSourceFactory(Element element) {
		String delimiter = $(element).attr("delimiter");
		String quote = $(element).attr("quote");
		if(StringUtils.isBlank(delimiter))
			this.delimiter = CSV_DEFAULT_DELIMITER;
		else
			this.delimiter = delimiter.charAt(0);
			
		if(StringUtils.isBlank(quote))
			this.quote = CSV_DEFAULT_QUOTE;			
		else 
			this.quote = quote.charAt(0);
		String trimAll = $(element).attr("trimAll");
		if(StringUtils.isBlank(trimAll))
			this.trimValues = true;
		else
			this.trimValues = BooleanUtils.toBoolean(trimAll);
	}

	/**
	 * get delimiter
	 * @return delimiter
	 */
	public Character getDelimiter() {
		return delimiter;
	}
	/**
	 * get quote
	 * @return quote
	 */
	public Character getQuote() {
		return quote;
	}
	/**
	 * trim all values ?
	 * @return if trim all or not
	 */
	public boolean isTrimValues() {
		return trimValues;
	}
	/**
	 * set the delimiter
	 * @param delimiter the delimiter
	 */
	public void setDelimiter(Character delimiter) {
		this.delimiter = delimiter;
	}
	/**
	 * set the quote
	 * @param quote the quote
	 */
	public void setQuote(Character quote) {
		this.quote = quote;
	}
	/**
	 * set if the extraction process trim all values or not
	 * @param trimValues trim all values ?
	 */	
	public void setTrimValues(boolean trimValues) {
		this.trimValues = trimValues;
	}
	public SourceReader createSourceReader(Reader reader) {
		return new CsvReader(reader, delimiter, quote, trimValues);
	}
	public SourceReader createSourceReader(InputStream in) {
		return new CsvReader(in, delimiter, quote, trimValues);
	}
	public SourceWriter createSourceWriter(Writer writer) {
		return new CsvWriter(writer, delimiter, quote);
	}
	public SourceWriter createSourceWriter(OutputStream out) {
		return new CsvWriter(out, delimiter, quote);
	}
	
}
